package com.tyk.bookstore.back.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tyk.bookstore.back.common.core.util.AssertUtil;
import com.tyk.bookstore.back.common.core.util.IdGenerator;
import com.tyk.bookstore.back.common.core.util.ObjUtil;
import com.tyk.bookstore.back.system.manager.excel.model.PermissionExcelVo;
import com.tyk.bookstore.back.system.model.entity.PermissionDo;
import com.tyk.bookstore.back.system.model.query.PermissionAddQuery;
import com.tyk.bookstore.back.system.model.query.PermissionPageQuery;
import com.tyk.bookstore.back.system.model.query.PermissionUpdateQuery;
import com.tyk.bookstore.back.system.model.result.PermissionResultEnum;
import com.tyk.bookstore.back.system.model.vo.PermissionPageVo;
import com.tyk.bookstore.back.system.model.vo.PermissionSuggestionVo;
import com.tyk.bookstore.back.system.model.vo.PermissionVo;
import com.tyk.bookstore.back.system.repository.PermissionRepository;
import com.tyk.bookstore.back.system.repository.RolePermissionRepository;
import com.tyk.bookstore.back.system.service.PermissionService;
import com.tyk.bookstore.back.system.util.MapstructSystem;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.List;

@RequiredArgsConstructor
@Slf4j
@Service
public class PermissionServiceImpl implements PermissionService {
    private final MapstructSystem mapstructSystem;
    private final TransactionTemplate transactionTemplate;
    private final PermissionRepository permissionRepository;
    private final RolePermissionRepository rolePermissionRepository;


    @Override
    public List<PermissionSuggestionVo> getSuggestionList() {
        LambdaQueryWrapper<PermissionDo> w = Wrappers.lambdaQuery(PermissionDo.class);
        w.select(PermissionDo::getId, PermissionDo::getName);
        return mapstructSystem.toPermissionSuggestionVo(permissionRepository.selectList(w));
    }

    @Override
    public PermissionPageVo getPage(PermissionPageQuery query) {
        Page<PermissionDo> page = new Page<>(query.getPage(), query.getLimit());
        LambdaQueryWrapper<PermissionDo> w = buildPageWrapper(query);
        permissionRepository.selectPage(page, w);
        return mapstructSystem.toPermissionPageVo(page);
    }


    @Override
    public PermissionVo getById(Long id) {
        PermissionVo vo = permissionRepository.selectGetPermissionByIdVo(id);
        AssertUtil.notNull(vo, PermissionResultEnum.PERMISSION_NOT_FOUND);
        return vo;
    }

    @Override
    public void add(PermissionAddQuery query) {

        // 名称不重复
        AssertUtil.isFalse(
                permissionRepository.exist1Eq(
                        PermissionDo::getName, query.getName(), PermissionDo.class
                ),
                PermissionResultEnum.PERMISSION_NAME_ALREADY_EXISTS
        );

        // 权限字符串不重复
        AssertUtil.isFalse(
                permissionRepository.exist1Eq(
                        PermissionDo::getCode, query.getCode(), PermissionDo.class
                ),
                PermissionResultEnum.PERMISSION_CODE_ALREADY_EXISTS
        );

        // 插入权限信息
        PermissionDo permission = mapstructSystem.toPermissionDo(query);
        permission.setId(IdGenerator.id());
        permissionRepository.insert(
                permission
        );

    }

    @Override
    public void updateById(PermissionUpdateQuery query) {

        // 权限存在
        AssertUtil.isTrue(
                permissionRepository.exist1Eq(
                        PermissionDo::getId, query.getId(), PermissionDo.class
                ),
                PermissionResultEnum.PERMISSION_NOT_FOUND
        );

        // 名称不重复
        AssertUtil.isFalse(
                permissionRepository.exist1Eq1Ne(
                        PermissionDo::getName, query.getName(),
                        PermissionDo::getId, query.getId(),
                        PermissionDo.class
                ),
                PermissionResultEnum.PERMISSION_NAME_ALREADY_EXISTS
        );

        // 权限字符串不重复
        AssertUtil.isFalse(
                permissionRepository.exist1Eq1Ne(
                        PermissionDo::getCode, query.getCode(),
                        PermissionDo::getId, query.getId(),
                        PermissionDo.class
                ),
                PermissionResultEnum.PERMISSION_CODE_ALREADY_EXISTS
        );

        // 更新权限信息
        permissionRepository.updateById(
                mapstructSystem.toPermissionDo(query)
        );

    }

    @Override
    public void deleteById(Long id) {

        // 权限存在
        AssertUtil.isTrue(
                permissionRepository.exist1Eq(
                        PermissionDo::getId, id, PermissionDo.class
                ),
                PermissionResultEnum.PERMISSION_NOT_FOUND
        );

        // 删除权限表
        transactionTemplate.executeWithoutResult(status -> {
            permissionRepository.deleteById(id);
            rolePermissionRepository.deleteByPermissionId(id);
        });

    }

    @Override
    public List<PermissionExcelVo> getPermissionExcelVoList(PermissionPageQuery query) {
        LambdaQueryWrapper<PermissionDo> w = buildPageWrapper(query);
        List<PermissionDo> doList = permissionRepository.selectList(w);
        return mapstructSystem.toPermissionExcelVoList(doList);
    }

    @Override
    public void savePermissionExcelVoList(List<PermissionExcelVo> permissionList) {
        List<PermissionDo> doList = mapstructSystem.toPermissionDoList(permissionList);
        doList.forEach(it -> it.setId(IdGenerator.id()));
        permissionRepository.insertBatch(doList);
    }


    /**
     * 构建分页查询Wrapper
     *
     * @param query 参数
     * @return Wrapper
     */
    private LambdaQueryWrapper<PermissionDo> buildPageWrapper(PermissionPageQuery query) {

        LambdaQueryWrapper<PermissionDo> w = Wrappers.lambdaQuery(PermissionDo.class);

        w.like(ObjUtil.notBlank(query.getName()), PermissionDo::getName, query.getName());

        w.like(ObjUtil.notBlank(query.getCode()), PermissionDo::getCode, query.getCode());

        w.like(ObjUtil.notBlank(query.getGroupName()), PermissionDo::getGroupName, query.getGroupName());

        w.ge(query.getStartTime() != null, PermissionDo::getCreateTime, query.getStartTime());
        w.le(query.getEndTime() != null, PermissionDo::getCreateTime, query.getEndTime());

        w.orderBy(true, false, PermissionDo::getCreateTime);

        return w;
    }
}
